/// 页面 * 主界面

<template>
  <AConfigProvider :locale="zhCN">
    <!-- 布局 -->
    <ALayout class="main">
      <!-- 布局-头 -->
      <ALayoutHeader class="header">
        Header
        {{ menu.selectedKeys }}
        <button @click="refreshMenu"> Refresh </button>
      </ALayoutHeader>
      <!-- 布局-体 -->
      <ALayout class="body">
        <!-- 布局-侧栏 -->
        <ALayoutSider :width="sider.width" class="sider">
          <!-- 菜单 -->
          <div :ref="sider.scrollbar" v-resize:0="sider.onResize" class="scrollbar">
            <AMenu
              v-model:selected-keys="menu.selectedKeys"
              v-model:open-keys="menu.openKeys"
              v-resize:0="sider.onResize"
              :items="menu.items"
              mode="inline"
              theme="dark"
              @select="menu.onSelect"
            />
          </div>
        </ALayoutSider>
        <!-- 布局-内容 -->
        <ALayoutContent class="content">
          <!-- 加载器 -->
          <ExLoading :loading="loading.value">
            <RouterView v-slot="{ Component, route }">
              <Transition name="fade-transform" mode="out-in">
                <component :is="Component" :key="route.path" />
              </Transition>
            </RouterView>
          </ExLoading>
        </ALayoutContent>
      </ALayout>
    </ALayout>
  </AConfigProvider>
</template>

<script setup lang="ts">
import PerfectScrollbar from 'perfect-scrollbar'
import 'perfect-scrollbar/css/perfect-scrollbar.css'
import zhCN from 'ant-design-vue/es/locale/zh_CN'
import type { MenuProps } from 'ant-design-vue'
import type { RouteRecordRaw } from 'vue-router'
import { groupBy } from 'lodash-es'
// import { ResizeComponent, resizeDirective as vResizeObserver  } from 'v-resize-observer'
import demoRoutes from '@/router/routes/demo.routes'
import router from '@/router'

//# 类型

type Menu = Required<Pick<MenuProps, 'selectedKeys' | 'openKeys' | 'items' | 'onSelect'>>

type State = {
  menuMap: Entity<RouteRecordRaw>
  menuItems: Menu['items']
}

//# 成员

/** 数据 */
const state: State = {
  menuMap: {},
  menuItems: [],
}
{
  state.menuItems = Object.entries(groupBy(demoRoutes, 'meta.group')).map(([group, routes]) => {
    return {
      key: group,
      label: group,
      children: routes.map((route) => {
        state.menuMap[route.path] = route
        return {
          key: route.path,
          label: (route.name as string).slice(4),
        }
      }),
    }
  })
}

// console.log(state.menuItems)

/** 加载器 */
const loading = useLoading()

/** 路由 */
const route = useRoute()

//// 菜单 ////

/** 菜单-数据 */

/** 菜单 */
const menu = shallowReactive({
  selectedKeys: [],
  openKeys: ['Demo'],
  items: state.menuItems,
  onSelect({ selectedKeys }) {
    router.push((menu.selectedKeys = selectedKeys)[0] as string)
  },
} as Menu)

/** 菜单 # 刷新  */
const refreshMenu = () => {
  router.push(`/redirect${route.fullPath}`)
}

//// 菜单-侧栏 ////

const sider = shallowReactive<{
  scrollbar: Ref<HTMLDivElement | undefined>
  ps?: PerfectScrollbar
  width: Key
  expand: () => void
  collapse: () => void
  onResize: () => void
}>({
  scrollbar: ref(),
  width: 0,
  onResize: () => {
    sider.ps?.update()
  },
  expand() {
    sider.width = 210
  },
  collapse() {
    sider.width = 0
  },
})

//# 周期

onMounted(() => {
  sider.ps = new PerfectScrollbar(sider.scrollbar.value!, {
    suppressScrollX: true,
    scrollYMarginOffset: 3,
  })
  setTimeout(() => {
    sider.expand()
  }, 50)
})

watchEffect(() => {
  const routeItem = state.menuMap[route.path]
  if (routeItem && !menu.selectedKeys.includes(route.path)) {
    menu.selectedKeys = [route.path]
  }
})

//# 方法
</script>

<style scoped lang="scss">
.main {
  height: 100vh;
  overflow: hidden;

  > .header {
    height: 50px;
    color: #fff;
  }

  > .body {
    > .sider {
      .scrollbar {
        position: relative;
        height: 100%;
        overflow: hidden;
        /* max-height: 100%;; */
      }
    }

    > .content {
      overflow: hidden;

      > :deep(.ex-loading) {
        height: 100%;

        > .ant-spin-container {
          height: 100%;
        }

        .ant-spin-spinning {
          max-height: inherit;
        }
      }
    }
  }
}
</style>
